package jp.co.systemi.asp.workflow.apply;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Logger;

import jp.co.systemi.asp.utils.ConfirmDialog;
import jp.co.systemi.asp.utils.DModalWindow;
import jp.co.systemi.asp.workflow.ICallback;
import jp.co.systemi.asp.workflow.Main;
import jp.co.systemi.asp.workflow.data.PaidHoliday;
import jp.co.systemi.asp.workflow.data.User;
import jp.co.systemi.asp.workflow.data.UserMeta;
import jp.co.systemi.asp.workflow.model.PaidHolidayApplyModel;

import org.apache.wicket.Page;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.extensions.markup.html.form.DateTextField;
import org.apache.wicket.extensions.yui.calendar.DatePicker;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.protocol.http.WebRequest;
import org.slim3.datastore.Datastore;

import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

public class PaidHolidayApply extends Main implements ICallback {
    /**
     * ログ出力 クラス名をあわせること
     */
    private static final Logger log = Logger.getLogger(PaidHolidayApply.class
            .getName());
    PaidHolidayApplyModel base = null;
    PaidHoliday edit = new PaidHoliday();
    TextField<Double> wi_remainingDays = null;

    /**
     * コンストラクター 画面の生成、イベント処理の定義はすべて、この中で完結する
     */
    public PaidHolidayApply() {
        init();
    }

    private void init() {
        // データストアーから初期化する入力項目の生成は一番先に行う
        UserService userService = UserServiceFactory.getUserService();

        com.google.appengine.api.users.User usr = userService.getCurrentUser();
        String loginId = usr.getEmail();
        UserMeta um = UserMeta.get();
        User mailSender = Datastore.query(um).filter(um.loginId.equal(loginId)).asSingle();
        base = new PaidHolidayApplyModel(loginId, mailSender);
        base.loadMaster();
        base.loadEditingHolidays();
        base.loadHolidays(loginId);
        // Formを生成する
        final Form<PaidHoliday> form = new MainForm<PaidHoliday>(this,
                "wi_applyPaidHolidayForm");
        // 有給休暇リスト
        final WebMarkupContainer tblHoliday = new WebMarkupContainer(
                "wi_tblPaidHoliday");
        tblHoliday.setOutputMarkupId(true);
        form.add(tblHoliday);
        tblHoliday.add(new AjaxButton("wi_btnAdd") {
            private static final long serialVersionUID = -2573012794536636414L;

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                try {
                    // 申請者を設定
                    UserService userService = UserServiceFactory.getUserService();

                    com.google.appengine.api.users.User usr = userService
                            .getCurrentUser();
                    edit.setLoginId(usr.getEmail());
                    base.regEditingHoliday(edit);
                } catch (Exception e) {
                    error(e.getMessage());
                    target.addComponent(feedback);
                    return;
                }
                // 残日数を減らす
                base.getMaster().setRemainingDays(base.getMaster().getRemainingDays()
                        - edit.getDays());

                edit.setStartDate(null);
                edit.setEndDate(null);
                edit.setDays(null);
                edit.setMemo("");
                // メッセージをクリア
                target.addComponent(feedback);
                // テーブル再表示
                target.addComponent(tblHoliday);
                // 残日数を再表示
                target.addComponent(wi_remainingDays);
            }
        });
        tblHoliday.add(new ListView<PaidHoliday>("wi_trPaidHoliday",
                base.getToApply()) {
            private static final long serialVersionUID = 4846361379394092695L;

            @Override
            protected void populateItem(ListItem<PaidHoliday> item) {
                final PaidHoliday holiday = item.getModelObject();
                SimpleDateFormat sdf = new SimpleDateFormat(
                        getString("date.format"));
                item.add(new Label("wi_tdSeq", new PropertyModel<Integer>(
                        holiday, "seq")));
                item.add(new Label("wi_tdStartDate", sdf.format(holiday
                        .getStartDate())));
                item.add(new Label("wi_tdEndDate", sdf.format(holiday
                        .getEndDate())));
                item.add(new Label("wi_tdDays", new PropertyModel<Double>(
                        holiday, "days")));
                item.add(new Label("wi_tdMemo", new PropertyModel<String>(
                        holiday, "memo")));

                item.add(new AjaxLink<Object>("wi_tdDelete") {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        log.info("delete");
                        Datastore.delete(holiday.getId());
                        base.getToApply().remove(holiday);
                        base.getMaster().setRemainingDays(base.getMaster()
                                .getRemainingDays()
                                + holiday.getDays());
                        // 順番を振りなおし
                        int i = 0;
                        for (PaidHoliday apply : base.getToApply()) {
                            apply.setSeq(++i);
                        }
                        target.addComponent(form);
                    }

                });
                item.add(new AjaxLink<Object>("wi_tdEdit") {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        log.info("edit");
                        Datastore.delete(holiday.getId());
                        base.getToApply().remove(holiday);
                        edit.setStartDate(holiday.getStartDate());
                        edit.setEndDate(holiday.getEndDate());
                        edit.setDays(holiday.getDays());
                        edit.setMemo(holiday.getMemo());
                        base.getMaster().setRemainingDays(base.getMaster()
                                .getRemainingDays()
                                + holiday.getDays());
                        // 順番を振りなおし
                        int i = 0;
                        for (PaidHoliday apply : base.getToApply()) {
                            apply.setSeq(++i);
                        }
                        target.addComponent(form);
                    }

                });
            }
        });
        // 編集エリア
        tblHoliday.add(new DateTextField("wi_tdEditStartDate",
                new PropertyModel<Date>(edit, "startDate"),
                getString("date.format")).add(new DatePicker()));

        tblHoliday.add(new DateTextField("wi_tdEditEndDate",
                new PropertyModel<Date>(edit, "endDate"),
                getString("date.format")).add(new DatePicker()));
        tblHoliday.add(new TextField<Double>("wi_tdEditDays",
                new PropertyModel<Double>(edit, "days")));
        tblHoliday.add(new TextField<String>("wi_tdEditMemo",
                new PropertyModel<String>(edit, "memo")));

        tblHoliday
                .add(new ListView<PaidHoliday>("wi_trApproved", base.getHolidays()) {
                    private static final long serialVersionUID = 4846361379394092695L;

                    @Override
                    protected void populateItem(ListItem<PaidHoliday> item) {
                        SimpleDateFormat sdf = new SimpleDateFormat(
                                getString("date.format"));
                        final PaidHoliday holiday = item.getModelObject();
                        item.add(new Label("wi_tdHolidaySeq",
                                new PropertyModel<Integer>(holiday, "seq")));
                        item.add(new Label("wi_tdHolidayStartDate", sdf
                                .format(holiday.getStartDate())));
                        item.add(new Label("wi_tdHolidayEndDate", sdf
                                .format(holiday.getEndDate())));
                        item.add(new Label("wi_tdHolidayDays",
                                new PropertyModel<Double>(holiday, "days")));
                        item.add(new Label("wi_tdHolidayMemo",
                                new PropertyModel<String>(holiday, "memo")));
                        item.add(new Label("wi_tdHolidayStatus",
                                new PropertyModel<String>(holiday, "status")));
                    }
                });

        wi_remainingDays = new TextField<Double>("wi_remainingDays",
                new PropertyModel<Double>(base.getMaster(), "remainingDays"));
        wi_remainingDays.setOutputMarkupId(true);
        form.add(wi_remainingDays);
        // 残日数を変更した場合の確認モデルウィンドウ
        final DModalWindow confirmWindow4RemainingDays = new DModalWindow(
                "wi_confirm");
        confirmWindow4RemainingDays.setTitle("確認ダイアログ");
        confirmWindow4RemainingDays
                .setPageCreator(new ModalWindow.PageCreator() {
                    private static final long serialVersionUID = -6364600063465337078L;

                    public Page createPage() {
                        return new ConfirmDialog(PaidHolidayApply.this,
                                confirmWindow4RemainingDays,
                                getString("confirm.message"));
                    }
                });
        confirmWindow4RemainingDays
                .setOKActionCallback(new ModalWindow.WindowClosedCallback() {
                    private static final long serialVersionUID = -1012735996565367949L;

                    public void onClose(AjaxRequestTarget target) {
                        log.info("update remaining days to datastore. "
                                + base.getMaster().getRemainingDays());
                        // OKボタンを押下
                        Datastore.put(base.getMaster());
                        // 表示には編集中の分を減らす
                        for (PaidHoliday holiday : base.getToApply()) {
                            base.getMaster().setRemainingDays(base.getMaster()
                                    .getRemainingDays()
                                    - holiday.getDays());
                        }
                        target.addComponent(wi_remainingDays);
                        target.addComponent(feedback);
                    }
                });
        confirmWindow4RemainingDays
                .setCancelActionCallback(new ModalWindow.WindowClosedCallback() {
                    private static final long serialVersionUID = -1012735996565367949L;

                    public void onClose(AjaxRequestTarget target) {
                        target.addComponent(wi_remainingDays);
                    }
                });
        confirmWindow4RemainingDays
                .setCloseButtonCallback(new ModalWindow.CloseButtonCallback() {
                    private static final long serialVersionUID = -2205343604513004971L;

                    public boolean onCloseButtonClicked(AjaxRequestTarget target) {
                        return true;
                    }
                });
        main.add(confirmWindow4RemainingDays);

        // 変更内容を即時にモデルに反映する
        OnChangeAjaxBehavior onChangeAjaxBehavior = new OnChangeAjaxBehavior() {
            private static final long serialVersionUID = 2034006790901866727L;

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                log.info("残日数は" + base.getMaster().getRemainingDays());
            };
        };
        wi_remainingDays.add(onChangeAjaxBehavior);

        form.add(new AjaxButton("wi_setRemainingDays") {
            private static final long serialVersionUID = 1L;

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                // 確認ダイアログを表示
                confirmWindow4RemainingDays.setInitialWidth(300);
                confirmWindow4RemainingDays.setInitialHeight(200);
                confirmWindow4RemainingDays.setWindowClosedCallback(null);
                confirmWindow4RemainingDays.show(target);
            }

        });
        // 承認者確認モデルウィンドウ
        final DModalWindow applyWindow = new DModalWindow("wi_applyModelWindow");
        applyWindow.setTitle(getString("applydialog.title"));
        applyWindow.setPageCreator(new ModalWindow.PageCreator() {
            private static final long serialVersionUID = -6364600063465337078L;

            public Page createPage() {
                return new ApplyDialog(PaidHolidayApply.this, applyWindow);
            }
        });

        applyWindow.setOKActionCallback(new ModalWindow.WindowClosedCallback() {
            private static final long serialVersionUID = -1012735996565367949L;

            public void onClose(AjaxRequestTarget target) {
                String memo = (String) applyWindow.getRetValue();
                base.processApplies(((WebRequest) getRequest())
                        .getHttpServletRequest(), memo);
                target.addComponent(feedback);
                target.addComponent(tblHoliday);

                setResponsePage(new ApplyRef());
            }
        });
        applyWindow
                .setCancelActionCallback(new ModalWindow.WindowClosedCallback() {
                    private static final long serialVersionUID = -1012735996565367949L;

                    public void onClose(AjaxRequestTarget target) {
                    }
                });
        // 閉じるボタン（X）をクリックした時に呼ばれる
        applyWindow
                .setCloseButtonCallback(new ModalWindow.CloseButtonCallback() {
                    private static final long serialVersionUID = -2205343604513004971L;

                    public boolean onCloseButtonClicked(AjaxRequestTarget target) {
                        return true;
                    }
                });
        main.add(applyWindow);
        tblHoliday.add(new AjaxButton("wi_btnApply") {
            private static final long serialVersionUID = 1L;

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                try{
                    base.onApply();
                }
                catch(Exception e){
                    error(e.getMessage());
                    target.addComponent(feedback);
                    return;
                }
                try {
                    base.loadApprovers();
                } catch (Exception e) {
                    error(e.getMessage());
                    target.addComponent(feedback);
                    return;
                }
                applyWindow.setInitialHeight(400);
                applyWindow.setWindowClosedCallback(null);
                applyWindow.show(target);
                log.info("after show dialog");
            }
        });
    }

    /**
     * Callback ダイアログ操作中に、呼び出し元を更新する場足は、ここで実装できる
     */
    public void setResult(PageParameters pars) {
        // if ("OK".equals(pars.getString("confirm"))) {
        // }
        // if ("OK".equals(pars.getString("apply"))) {
        // }
    }

    public Object getDefault(PageParameters pars) {
        return base.getApprovers();
    }

    public String getEmptyMessage(PageParameters pars) {
        return getString("apply.reason.empty");
    }
}
